package com.yonyou.ucf.mdf.app.mobile.module;

import com.alibaba.fastjson.JSON;
import com.yonyou.diwork.exception.DiworkRuntimeException;
import com.yonyou.iuap.context.InvocationInfoProxy;
import com.yonyou.workbench.cons.Constants;
import com.yonyou.workbench.util.SDKResultUtils;
import com.yonyou.yht.sdk.SDKUtils;
import com.yonyou.yht.sdkutils.JsonResponse;
import com.yonyou.yht.sdkutils.SdkConsts;
import com.yonyou.yht.sdkutils.YhtClientPropertyUtil;
import com.yonyou.yht.sdkutils.sign.SignEntity;
import com.yonyou.yht.sdkutils.sign.SignMake;
import com.yonyoucloud.iuap.ucf.mdd.starter.ucg.openapi.isv.router.module.crypto.CryptoApi;
import com.yonyoucloud.iuap.ucf.mdd.starter.ucg.openapi.isv.router.module.isvrequest.ISVRequest;
import com.yonyoucloud.iuap.ucf.mdd.starter.ucg.openapi.isv.router.module.isvrequest.ISVRequestBody;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;
import java.util.*;
import java.util.Map.Entry;

@RequiredArgsConstructor
@Service
@Slf4j
public class MobileYhtContextSetupService {

    private static String defaultSysId = YhtClientPropertyUtil.getSdkPropertyByKey("sysid");
    private static String casurl = YhtClientPropertyUtil.getSdkPropertyByKey("cas.url");

    private static Method getLocaleMethod = null;
    private static String PROFILE_VALUE;
    private static Boolean OK_PROFILE = null;

    private final ISVRequest isvRequest;
    private final CryptoApi cryptoApi;

    public Map<String, Object> buildYhtAccessTokenContext(String tenantId, String userId, Locale locale) {
        Map<String, Object> map = new HashMap<>();
        //租户ID
        map.put("tenantId", tenantId);
        //当前系统
        map.put("syscode", "U8C3");
        //设置业务日期
        map.put("businessDate", null);
        //产品线
        map.put(Constants.PRODUCT_LINE, "diwork");

        return map;
    }

    public String syncYhtAccessTokenContextInfo(String yhtAccessToken, Map<String, Object> context) {
        String syncResult = setUserCurrentTenant(yhtAccessToken, context);
        if (SDKResultUtils.getData(syncResult).isSuccess()) {
            return parseVersionToken(syncResult, yhtAccessToken);
        }
        String errorMessage = String
                .format("setUserCurrentTenant error!! token:%s,values:%s,result:%s", yhtAccessToken, JSON.toJSONString(context), syncResult);
        log.error(errorMessage);
        throw new DiworkRuntimeException("友户通服务异常", new RuntimeException(errorMessage));
    }

    private String parseVersionToken(String setTenantResult, String yhtAccessToken) {
        String versionToken = null;
        try {
            versionToken = JSON.parseObject(setTenantResult).getString("version");
        } catch (Exception e) {
            log.warn("exception when get version token", e);
        }
        if (StringUtils.isNotBlank(versionToken)) {
            return versionToken;
        }
        return yhtAccessToken;
    }

    private String setUserCurrentTenant(String yhtAccessToken, Map<String, Object> tenantMap) {
        JsonResponse jsonStr = new JsonResponse();
        if (StringUtils.isBlank(yhtAccessToken)) {
            jsonStr.failed("token is empty");
            return SDKUtils.gson.toJson(jsonStr);
        } else if (tenantMap.isEmpty()) {
            jsonStr.failed("tenantMap is empty");
            return SDKUtils.gson.toJson(jsonStr);
        } else {
            String url = casurl + SdkConsts.USER_URL_SET_CURRENT_TENANT;
            Map<String, String> params = new HashMap();
            params.put("token", yhtAccessToken);
            params.put("tenantInfo", SDKUtils.gson.toJson(tenantMap));
            params.put("sysId", defaultSysId);
            return originalSignPost(url, params, false);
        }
    }

    private String originalSignPost(String url, Map<String, String> params, boolean isExternal) {
        params = getNoNullParam(params);
        SignEntity signEntity = SignMake.signEntity(url, params, SignMake.SIGNPOST);
        Map<String, String> headers = new LinkedHashMap();
        headers.put("sign", signEntity.getSign());
        headers.put("sysid", defaultSysId);
        if (isExternal) {
            headers.put("external", "EXTERNAL");
        }
        headers.put("locale", getLocale());
        headers.put("sdkversion", "5.0.0");
        handlerHeaderProfile(headers);
        ISVRequestBody isvRequestBody = new ISVRequestBody();
        isvRequestBody.setUrl(signEntity.getSignURL());
        isvRequestBody.setRequestMethod("POST");
        isvRequestBody.setParams(params);
        isvRequestBody.setHeaders(headers);
        return isvRequest.doRequest(InvocationInfoProxy.getTenantid(), isvRequestBody);
    }

    private Map<String, String> getNoNullParam(Map<String, String> params) {
        if (params == null) {
            return null;
        } else {
            Map<String, String> newparams = new HashMap();
            Iterator iterator = params.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry<String, String> entry = (Entry) iterator.next();
                if (StringUtils.isNotBlank((String) entry.getValue())) {
                    newparams.put(entry.getKey(), entry.getValue());
                }
            }
            return newparams;
        }
    }

    private String getLocale() {
        if (getLocaleMethod == null) {
            return null;
        } else {
            try {
                Object obj = getLocaleMethod.invoke((Object) null);
                return obj == null ? null : (String) obj;
            } catch (Exception e) {
                return null;
            }
        }
    }

    private void handlerHeaderProfile(Map<String, String> headers) {
        String profile = getProfile();
        if (StringUtils.isNotEmpty(profile)) {
            headers.put("profile", profile);
        }
    }

    private String getProfile() {
        if (StringUtils.isNotEmpty(PROFILE_VALUE)) {
            return PROFILE_VALUE;
        }
        if (Boolean.FALSE.equals(OK_PROFILE)) {
            return PROFILE_VALUE;
        }
        try {
            Class<?> areClass = Class.forName("com.yonyou.cloud.middleware.AppRuntimeEnvironment");
            Method getProfileMethod = areClass.getMethod("getProfile", new Class[0]);
            PROFILE_VALUE = (String) getProfileMethod.invoke(null, new Object[0]);
            OK_PROFILE = Boolean.valueOf(StringUtils.isNotEmpty(PROFILE_VALUE));
        } catch (Exception e) {
            log.warn("getProfile warn", e);
            OK_PROFILE = Boolean.valueOf(false);
        }
        return null;
    }

}
